package cn.lx.es.query.search.service;

import cn.lx.es.query.search.entity.Attach;
import cn.lx.es.query.search.entity.PageList;
import cn.lx.es.query.search.entity.PageSortHighLight;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.index.query.QueryBuilder;

import java.util.List;

/**
 * @ClassName ElasticsearchTemplate
 * @Description: es通用服务操作
 * @Author: 落雪
 * @CreateDate: 2025/7/3 08:43
 * @UpdateUser: 落雪
 * @UpdateDate: 2025/7/3 08:43
 * @UpdateRemark:
 * @Version: 1.0
 */
public interface ElasticsearchTemplate<T, M> {


    /**
     * 通过Low Level REST Client 查询
     * https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.6/java-rest-low-usage-requests.html
     *
     * @param request
     * @return
     * @throws Exception
     */
    Response request(Request request) throws Exception;

    /**
     * 插入文档
     *
     * @param t
     * @throws Exception
     */
    void save(T t) throws Exception;

    /**
     * 同步插入文档
     *
     * @param t
     * @throws Exception
     */
    void syncSave(T t) throws Exception;

    /**
     * 插入索引集合
     */
    void save(List<T> list) throws Exception;

    /**
     * 同步插入文档集合
     *
     * @param list
     * @throws Exception
     */
    void syncSave(List<T> list) throws Exception;

    /**
     * 按照有值字段更新索引
     *
     * @param t
     */
    boolean update(T t) throws Exception;

    /**
     * 批量更新部分字段
     *
     * @param list
     * @return
     * @throws Exception
     */
    void update(List<T> list) throws Exception;

    /**
     * 删除索引
     *
     * @param t
     */
    boolean delete(T t) throws Exception;

    /**
     * 删除索引
     *
     * @param id
     */
    boolean deleteById(M id, Class<T> clazz) throws Exception;

    /**
     * 【最原始】查询
     *
     * @param searchRequest
     * @return
     * @throws Exception
     */
    SearchResponse search(SearchRequest searchRequest) throws Exception;

    /**
     * 支持分页、高亮、排序的查询
     * @param queryBuilder 查询条件
     * @param pageSortHighLight 分页+排序+高亮对象封装
     * @param clazz 索引pojo类类型
     * @return
     * @throws Exception
     */
    PageList<T> search(QueryBuilder queryBuilder, PageSortHighLight pageSortHighLight, Class<T> clazz) throws Exception;


    /**
     * 支持分页、高亮、排序的查询（跨索引）
     * @param queryBuilder 查询条件
     * @param pageSortHighLight 分页+排序+高亮对象封装
     * @param clazz 索引pojo类类型
     * @param indexs 索引名称
     * @return
     * @throws Exception
     */
    PageList<T> search(QueryBuilder queryBuilder, PageSortHighLight pageSortHighLight, Class<T> clazz,String... indexs) throws Exception;


    /**
     * 支持分页、高亮、排序、指定返回字段、路由的查询
     * @param queryBuilder 查询条件
     * @param attach 查询增强对象（可支持分页、高亮、排序、指定返回字段、路由、searchAfter信息的定制）
     * @param clazz 索引pojo类类型
     * @return
     * @throws Exception
     */
    PageList<T> search(QueryBuilder queryBuilder, Attach attach, Class<T> clazz) throws Exception;


    /**
     * 支持分页、高亮、排序、指定返回字段、路由的查询（跨索引）
     * @param queryBuilder 查询条件
     * @param attach 查询增强对象（可支持分页、高亮、排序、指定返回字段、路由、searchAfter信息的定制）
     * @param clazz 索引pojo类类型
     * @param indexs 索引名称
     * @return
     * @throws Exception
     */
    PageList<T> search(QueryBuilder queryBuilder, Attach attach, Class<T> clazz,String... indexs) throws Exception;
    /**
     * TODO 这里回头有时间研究一下jpa的原理，如何能够直接给interface生成代理类，并托管spring
     * 非分页查询
     * 目前暂时传入类类型
     *
     * @param queryBuilder
     * @param clazz
     * @return
     * @throws Exception
     */
    List<T> search(QueryBuilder queryBuilder, Class<T> clazz) throws Exception;

    /**
     * scroll方式查询(默认了保留时间为Constant.DEFAULT_SCROLL_TIME)
     *
     * @param queryBuilder
     * @param clazz
     * @return
     * @throws Exception
     */
    List<T> scroll(QueryBuilder queryBuilder, Class<T> clazz) throws Exception;

    /**
     * scroll方式查询
     *
     * @param queryBuilder
     * @param clazz
     * @param time         保留小时
     * @return
     * @throws Exception
     */
    List<T> scroll(QueryBuilder queryBuilder, Class<T> clazz, long time) throws Exception;

    /**
     * 搜索建议
     *
     * @param fieldName
     * @param fieldValue
     * @param clazz
     * @return
     * @throws Exception
     */
    List<String> completionSuggest(String fieldName, String fieldValue, Class<T> clazz) throws Exception;

    /**
     * 根据ID查询
     *
     * @param id
     * @param clazz
     * @return
     * @throws Exception
     */
    T getById(M id, Class<T> clazz) throws Exception;

    /**
     * 根据ID列表批量查询
     *
     * @param ids
     * @param clazz
     * @return
     * @throws Exception
     */
    List<T> mgetById(M[] ids, Class<T> clazz) throws Exception;

    /**
     * id数据是否存在
     *
     * @param id
     * @param clazz
     * @return
     */
    boolean exists(M id, Class<T> clazz) throws Exception;
}
